home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Apple II Magazines (PO)
/
Nibble Volume 09, No. 11 (1988-11)(MicroSPARC)(Side A).zip
/
Nibble Volume 09, No. 11 (1988-11)(MicroSPARC)(Side A).po
/
SPEEDDRAW.0.S
< prev
next >
Wrap
Text File
|
1996-12-24
|
14KB
|
470 lines
*
* SPEEDDRAW Source Code
* by Jim Savage
* Copyright(c) 1988
* MicroSPARC, Inc.
* Concord, MA 01742
*
* Merlin assembler
*
* Equates for installation
*
DISTANCE EQU $00
LENGTH EQU $2F ;Length of command minus one
PCL EQU $3A ;Pointer for disassembly
A1L EQU $3C
A2L EQU $3E
A4L EQU $42
STREND EQU $6F
HIMEM EQU $73
AMPER EQU $3F5
INSDS2 EQU $F88C ;Monitor disassembly routine
MOVE EQU $FE2C
GETBUF EQU $BEF5
*
ORG $4069
*
LDY #$0A
LDA AMPER+1
STA PCL
LDA AMPER+2
STA PCL+1
]LOOP LDA (PCL),Y ;Look at memory where ampersand points
CMP INTERP,Y ;See if it's Ampertrig
BNE INSTALL ;Not same so install
DEY ;Check another byte
BNE ]LOOP ;Until 10 are OK
RTS ;Don't want to repeat installation
*
INSTALL LDA AMPER+1 ;Get old vector
STA OLDVEC+1 ; and link
LDA AMPER+2 ; so it can
STA OLDVEC+2 ; still be used
LDA #$4C ;JMP instruction
STA AMPER
*
LDA $BF00 ;Check for Prodos
CMP #$4C
BEQ PRO ;Yes, use GETBUF
*
LDA HIMEM+1 ;Get old HIMEM location
SEC
SBC #$04 ;Need 4 pages of memory
STA HIMEM+1 ;Move it down
STA STREND+1 ;Also the string start
BNE SETPTRS ;Always
*
PRO LDA #04
JSR GETBUF ;Ask for 4 page buffer
*
SETPTRS STA A4L+1 ;Point MOVE to new home
STA AMPER+2 ;And point ampersand vector at it
STA GOTCMD+1 ;Take care of high byte
SEC
SBC #>INTERP ;Find how far to move
STA DISTANCE
*
LDA #>INTERP ;Start of resident part
STA PCL+1 ;Put in relocation pointer
STA A1L+1 ; and in MOVE origin
LDY #00 ;Put
STY PCL ; zero
STY AMPER+1 ; in
STY A1L ; various
STY A4L ; places
STY STREND ;
STY HIMEM ;
*
RELOC8 LDX #00
JSR INSDS2 ;Disassemble an instruction
LDY LENGTH ;How long?
CPY #02 ;A 3-byter?
BNE NXTINST
LDA (PCL),Y ;Get the 3rd byte
CMP #>INSTALL ;Below our code?
BMI NXTINST ;Yes, don't adjust
CMP #>END+$100 ;Above our code?
BPL NXTINST ;Yes, don't adjust
CLC
ADC DISTANCE ;Adjust the address
STA (PCL),Y ;Put it back
NXTINST INY
TYA
CLC
ADC PCL ;Advance the pointer
STA PCL
BCC NOPAGE
INC PCL+1
NOPAGE LDY #00
LDA (PCL),Y ;Look at next byte
BNE RELOC8 ;If not zero, keep on
*
LDA #<END-1
STA A2L ;Finish preparing for MOVE
LDA #>END-1
STA A2L+1
JMP MOVE ;Exit via the move
*
* Equates for resident routine
*
ANG1 EQU $00
QUAD1 EQU $01
ANG2 EQU $02
QUAD2 EQU $03
XCH EQU $04
XCL EQU $05
YCH EQU $06
YCL EQU $07
RAD EQU $08
VARTAB EQU $69
TXTPTR EQU $B8
SINE EQU $2F0
SINRAD EQU $2F1
LOCENT EQU $2F2
HICENT EQU $2F3
SPEED EQU $2F4
COUNT EQU $2F6
HPLOT0 EQU $F457
*
*
INTERP LDY #00
LDX #09 ;End of command table
LDA (TXTPTR),Y ;Get command character
CMP #'&' ;Second ampersand?
BEQ TRYOLD ;Yes, so not an Ampertrig command
CMDLOOP CMP CMDTBL,X ;Look for match
BEQ GOTCMD ;Found
DEX
BPL CMDLOOP ;No, next
BMI OLDVEC
TRYOLD INC TXTPTR ;Step beyond ampersand
BNE OLDVEC
INC TXTPTR+1
OLDVEC JMP $0000 ;Send to address formerly in AMPER
GOTCMD LDA #$00 ;Loader puts hi byte of cmds here
PHA
LDA CALLTBL,X ;Set up the address
PHA ; for the "funny jump"
*
]LOOP INC TXTPTR ;Advance
BNE NOCARI2
INC TXTPTR+1
NOCARI2 LDA (TXTPTR),Y ; until
BEQ INPUTS ; zero
CMP #$3A ; or colon
BNE ]LOOP ;Keep looking
*
INPUTS LDX #00 ;Index to input targets
LDY #$02 ;Index to variable table
JSR TWOBYTE ;Move A1%
JSR TWOBYTE ;Move A2%
JSR TWOBYTE ;Move XC%
JSR TWOBYTE ;Move YC%
INY ;Just a low byte
JSR MOVBYTE ;Move R%
LDX #00 ;Index to ANG1
JSR DIV90 ;Convert degrees to Hex
LDX #02 ;Index to ANG2
JMP DIV90 ;Again, then funny jump to command
*
RAY JSR DODOT
LDA RAD ;Check if done
BEQ DONEVEC ;Yes
DEC RAD ;Next one
JMP RAY
*
DOTLIN LDA #03 ;Start in mid-dash
STA COUNT
]LOOP JSR BDOT ;Draw a dot or not
LDA RAD ;Check if done
BEQ DONEVEC ;Yes
DEC RAD
JMP ]LOOP ;Next
*
VECTOR LDA RAD
PHA ;Put radius aside
JSR RAY ;Draw the line
PLA ;Retrieve radius
STA RAD
MOVEC JSR GETX
LDY #$11 ;Index to XC% low
STA (VARTAB),Y ;Put away
STA XCL
LDA HICENT
DEY ;XC% high
STA (VARTAB),Y ; away
STA XCH
JSR GETY
LDY #$18 ;Index to YC% low
STA (VARTAB),Y ; away
STA YCL
LDA HICENT
DEY
STA (VARTAB),Y ;YC% high
STA YCH
DONEVEC RTS
*
BARC LDA #03 ;Start in mid-dash
STA COUNT
JSR SETSPD ;Set speed appropriate to radius
]LOOP JSR BDOT
JSR NXTANGL
BNE ]LOOP ;Another dot or not
JMP BDOT ;Last one
*
CIRCLE LDA #00 ;Zero the
STA ANG1 ; start
STA ANG2 ; and
STA QUAD1 ; finish
STA QUAD2 ; angles
*
ARC JSR SETSPD ;Set speed appropriate to radius
]LOOP JSR DODOT
JSR NXTANGL
BNE ]LOOP ;Another dot, else do last one
*
DODOT JSR GETY
SEC
CMP #192 ;Legal Y?
BCS RTS1 ;Too big, punt
LDY HICENT ;Hi byte <> 0?
BNE RTS1 ;Return without plotting
PHA ;Put Y aside
JSR GETX
TAX ;Put XL where HPLOT0 wants it
PLA ;Retrieve Y-coordinate
LDY HICENT ;Put XH where HPLOT0 wants it
BMI RTS1 ;Can't have negative X coord
CPY #01 ;Check for oversize X coord
BMI PLOTIT ;O.K.
BEQ CHEKLO ;Look at lo byte
RTS1 RTS ;Hi byte 2 or more, too big.
CHEKLO SEC
CPX #$18 ;X bigger than 279?
BCS RTS1 ;Yes, return without plotting
PLOTIT JMP HPLOT0 ;Dot done!
*
LTURN1 JMP LTURN ;Just so all commands are on 1 page
*
TURN INC QUAD1 ;Right turn
JSR MOVEC ;Set center
DEC QUAD1 ;Face
DEC QUAD1 ; outward
CLC
LDY #$0A
LDA (VARTAB),Y ;Get A2% lo
LDY #03
ADC (VARTAB),Y ;Add A1% lo
STA (VARTAB),Y ;Update A1% lo
STA QUAD2 ;Set finish angle
LDY #09
LDA (VARTAB),Y ;Likewise the hi bytes
LDY #02
ADC (VARTAB),Y
STA (VARTAB),Y ;Put in A1%
STA ANG2
LDX #02
JSR DIV90 ;Convert to hex degrees
DEC QUAD2 ;Face outward
JSR ARC
JMP MOVEC ;Set origin at end & exit
*
LTURN SEC
LDY #03
LDA (VARTAB),Y ;Get A1% low
LDY #$0A
SBC (VARTAB),Y ;Subtract A2% low
LDY #03
STA (VARTAB),Y ;New angle in A1% low
DEY
LDA (VARTAB),Y ;Likewise hi byte
LDY #09
SBC (VARTAB),Y
LDY #02
STA (VARTAB),Y
LDA ANG1 ;Move 1
STA ANG2 ; to 2
LDA QUAD1
STA QUAD2
DEC QUAD1 ;Face in
JSR MOVEC ;Set center
JSR GETA1 ;Get the (new) input A1%
INC QUAD2 ;Face out
JSR ARC ;Do turn
JSR GETA1 ;Restore (new) input A1%
JMP MOVEC ;Put center at end: Done
*
GETA1 LDX #00
LDY #02
JSR TWOBYTE ;Move input A1% to ANG1/QUAD1
LDX #00
JSR DIV90
INC QUAD1
RTS
*
SETSPD LDA QUAD2
AND #03 ;Always work in 1st 4 quadrants
STA QUAD2
LDA #$20 ;Speed=32 if RAD<=5
STA SPEED
LDA #05 ;Test criterion
RADTEST SEC
CMP RAD
BCS SET ;Speed found
ASL A ;Double criterion
LSR SPEED ;Halve speed
BNE RADTEST
INC SPEED ;Must be at least one
SET SEC
LDA #00
SBC SPEED ;Make mask for rounding angles
PHA ;Put clone aside
AND ANG1
STA ANG1
PLA ;Retrieve clone
AND ANG2
STA ANG2
RTS
*
NXTANGL CLC
LDA SPEED
ADC ANG1 ;Increment angle by 1,2,4 etc
STA ANG1
BCC CHECK
INC QUAD1 ;If last quad done
CHECK LDA QUAD1
AND #03 ;Stay in 4 quadrants
CMP QUAD2 ;In final quad?
BNE RTSA ;No, keep on
LDA ANG1
CMP ANG2 ;Same?
RTSA RTS ;Return w/ Z-flag set if done
*
BDOT LDA COUNT ;Where are we?
BNE NOTZED ;Still counting
LDA #04 ;Reset
STA COUNT
RTS
NOTZED CMP #02 ;In plot part of cycle?
BMI SKPDOT ;No, skip
JSR DODOT ;Make your point
SKPDOT DEC COUNT
RTS
*
GETY LDA YCL ;Prepare to calc Y-coordinate
STA LOCENT
LDA YCH ;Allow for center off screen
STA HICENT
DEC QUAD1 ;Get ready for cosine
JSR GETCOORD ;Go get Y-coordinate
INC QUAD1 ;Now for sine
RTS
*
GETX LDA XCH ;Get ready for X
STA HICENT
LDA XCL
STA LOCENT
JSR GETCOORD ;Go get x-coordinate
RTS
*
* Generate sine * radius
*
GETCOORD LDA QUAD1
AND #$01 ;Odd or even?
BEQ EVEN
LDA ANG1
BEQ SINONE ;Special case, sine=1
LDA #$00
SEC
SBC ANG1 ;Get complement of angle
CLC
BCC EVEN+2
EVEN LDA ANG1 ;Don't complement
SEC
CMP #$F6 ;Big enough that sine=1?
BCC LOOKUP ;No, look up sine
SINONE LDA RAD ;Yes, so the leg = the radius
STA SINRAD
JMP PLUSMNS
LOOKUP TAY ;Angle indexes the table
LDA SINTBL,Y ;Got the sine!
STA SINE
*
* Multiply radius by (co)sine *
*
LDA #$00
STA SINRAD
LDX #$08 ;Set bit index
]LOOP ASL A ;Shift
ROL SINRAD ; three
ASL SINE ; bytes
BCC NOCARI ;No carry, no add
CLC
ADC RAD
BCC NOCARI
INC SINRAD
NOCARI DEX ;Next bit
BNE ]LOOP
ASL A ;Round off to closest hi bit
BCC PLUSMNS
INC SINRAD
PLUSMNS LDA QUAD1
AND #02 ;In neg half of sine wave?
BNE SUBTRACT ;Yes
LDA LOCENT ;Get lo byte of center
CLC
ADC SINRAD ;Add (sine * radius)
BCC GOTIT
INC HICENT
GOTIT RTS
SUBTRACT LDA LOCENT ;Get lo byte of center
SEC
SBC SINRAD ;Subtract (sine * radius)
BCS GOTIT
DEC HICENT
RTS
*
TWOBYTE JSR MOVBYTE ;Move high byte
JSR MOVBYTE ;Move low byte
INY ;5 bumps
INY ; to get to
INY ; the next
INY ; variable
INY ; in the table
RTS
*
MOVBYTE LDA (VARTAB),Y ;Get byte from variable table
STA $00,X ;Put on zero page
INY ;Bump
INX ; indices
RTS
*
DIV90 LDA 00,X ;Look at hi byte (bytes rev!)
BPL DODIV ;If positive, proceed
CLC
ADC #$5A ;Add 360x64 to it
STA 00,X
DODIV LDY #00 ;Begin division
STY $00,X
LDY #$10 ;Bit index
]LOOP ASL $00,X
ROL $01,X
ROL A
CMP #$5A ;Bigger than 90?
BCC TOOBIG ;No
SBC #$5A
INC $00,X
TOOBIG DEY
BNE ]LOOP
RTS ;Return with bytes reversed
*
SINTBL DS $F6 ;Leave $F6 bytes for SIN table
*
CMDTBL ASC 'RDVMBCASLT'
CALLTBL DFB #<RAY-1,#<DOTLIN-1,#<VECTOR-1
DFB #<MOVEC-1,#<BARC-1
DFB #<CIRCLE-1,#<ARC-1,#<DODOT-1
DFB #<LTURN1-1,#<TURN-1
END EQU *
LST OFF